﻿#region Copyright (c) 2007-2009 Mikko Salmi, Contributors
/*
 * Copyright (c) 2007-2009 Mikko Salmi, Contributors
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 * 
*/
#endregion // Copyright

#region Notes

/*
 *  This code is based on development by Eric Schoonover, Eilon Lipton, Matt Swann, Mike Ammerlaan. Published in:
 *  http://www.capdes.com/2007/02/microsoft_office_sharepoint_se.html  
*/

#endregion // Notes

using System;
using System.Xml.Serialization;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Drawing;
using System.Web;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using System.Collections;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;

namespace CodePlex.WebParts
{
    [NonVisualControl]
    public class AdvancedWebPart : System.Web.UI.WebControls.WebParts.WebPart
    {
        private string validationGroupId;
        private ValidationSummary vsErrorDetails;
        private Panel pnlErrorDetails;
        private Label lblErrorMessage;
        private LinkButton lbShowErrorDetails;
        private ScriptManager scriptManager;

        /// <summary>
        /// Exposes the Page's script manager. The value is not set until after OnInit.
        /// </summary>
        [WebPartStorage(Storage.None)]
        public ScriptManager ScriptManager
        {
            get
            {
                return scriptManager;
            }
        }

        protected void InitScriptManager()
        {
            //get the existing ScriptManager if it exists on the page
            scriptManager = ScriptManager.GetCurrent(this.Page);

            if (scriptManager == null)
            {
                //create new ScriptManager and EnablePartialRendering
                scriptManager = new ScriptManager();
                scriptManager.EnablePartialRendering = true;

                // Fix problem with postbacks and form actions (DevDiv 55525)
                Page.ClientScript.RegisterStartupScript(typeof(AdvancedWebPart), this.ID, "_spOriginalFormAction = document.forms[0].action;", true);
                //tag:"form" att:"onsubmit" val:"return _spFormOnSubmitWrapper()" blocks async postbacks after the first one
                //not calling "_spFormOnSubmitWrapper()" breaks all postbacks
                //returning true all the time, somewhat defeats the purpose of the _spFormOnSubmitWrapper() which is to block repetitive postbacks, but it allows MS AJAX Extensions to work properly
                //its a hack that hopefully has minimal effect
                if (this.Page.Form != null)
                {
                    string formOnSubmitAtt = this.Page.Form.Attributes["onsubmit"];
                    if (!string.IsNullOrEmpty(formOnSubmitAtt) && formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
                    {
                        this.Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";
                    }

                    //add the ScriptManager as the first control in the Page.Form
                    //I don't think this actually matters, but I did it to be consistent with how you are supposed to place the ScriptManager when used declaritevly
                    this.Page.Form.Controls.AddAt(0, scriptManager);
                }
            }
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            validationGroupId = Guid.NewGuid().ToString();
            vsErrorDetails = new ValidationSummary();
            vsErrorDetails.ID = "_ErrorContainer";
            vsErrorDetails.ValidationGroup = validationGroupId;
            vsErrorDetails.BorderStyle = BorderStyle.Solid;
            vsErrorDetails.BorderWidth = Unit.Pixel(2);
            vsErrorDetails.BorderColor = Color.Red;
            vsErrorDetails.DisplayMode = ValidationSummaryDisplayMode.SingleParagraph;

            pnlErrorDetails = new Panel();
            pnlErrorDetails.Controls.Add(vsErrorDetails);
            pnlErrorDetails.Visible = false;

            lblErrorMessage = new Label();
            lblErrorMessage.ForeColor = Color.Red;
            lblErrorMessage.Visible = false;
            lblErrorMessage.Text = string.Empty;

            lbShowErrorDetails = new LinkButton();
            lbShowErrorDetails.Click += new EventHandler(lbShowErrorDetails_Click);
            lbShowErrorDetails.Text = "Show error details";
            lbShowErrorDetails.Visible = false;

            this.Controls.Add(lblErrorMessage);
            this.Controls.Add(lbShowErrorDetails);
            this.Controls.Add(pnlErrorDetails);
        }

        void lbShowErrorDetails_Click(object sender, EventArgs e)
        {
            if (pnlErrorDetails.Visible == false)
                pnlErrorDetails.Visible = true;
            else
                pnlErrorDetails.Visible = false;
        }

        public void RegisterError(string errorMessage)
        {
            RegisterError(errorMessage, string.Empty);
        }

        public void RegisterError(string errorMessage, string errorDetail)
        {
            if (this.Controls.Contains(lblErrorMessage))
            {
                int uniqueCounter;
                if (HttpContext.Current.Items["GetUniqueControlId"] != null)
                {
                    uniqueCounter = (int)HttpContext.Current.Items["GetUniqueControlId"];
                }
                else
                {
                    uniqueCounter = 0;
                }

                uniqueCounter++;
                HttpContext.Current.Items["GetUniqueControlId"] = uniqueCounter;

                CustomValidator cv = new CustomValidator();
                cv.ID = string.Concat("_Error_", uniqueCounter);
                cv.ValidationGroup = validationGroupId;
                cv.Display = ValidatorDisplay.None;
                cv.IsValid = false;
                cv.ErrorMessage = errorDetail;

                this.Controls.Add(cv);

                if (!string.IsNullOrEmpty(errorDetail))
                    lbShowErrorDetails.Visible = true;

                lblErrorMessage.Text = "Web part error: " + errorMessage;
                lblErrorMessage.Visible = true;
            }
            else
            {
                SPUtility.TransferToErrorPage("ErrorMessage: " + errorMessage + " ;ErrorDetail: " + errorDetail);
            }
        }

        public override EditorPartCollection CreateEditorParts()
        {
            LogoEditorPart logoEditorPart = new LogoEditorPart();
            logoEditorPart.ID = this.ID + "_logoEditorPart";

            logoEditorPart.GroupingText = "Ticker";

            List<EditorPart> parts = new List<EditorPart>();
            parts.Add(logoEditorPart);

            return new EditorPartCollection(parts);
        }

        public override object WebBrowsableObject
        {
            get { return this; }
        }

        /// <summary>
        /// Oninit fires before page load. Modifications to the page that are necessary to support Ajax are done here.
        /// </summary>
        protected override void OnInit(EventArgs e)
        {
            InitScriptManager();


            base.OnInit(e);
        }

   }
}